home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / freeWAIS-sf-1.1 / ir / server-single.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-13  |  20.6 KB  |  745 lines

  1. /* WIDE AREA INFORMATION SERVER SOFTWARE    
  2.    No guarantees or restrictions.  See the readme file for the full standard 
  3.    disclaimer.
  4.    5.29.90    Harry Morris, morris@think.com
  5. */
  6.  
  7. /* Copyright (c) CNIDR (see ../COPYRIGHT) */
  8.  
  9.  
  10. /* this file is a server process for a unix machine that takes input from 
  11.    standard in or from a socket and searches the local search engine on the 
  12.    unix box.
  13.    originally written by harry morris.
  14.    modified by brewster kahle. 7/90
  15.    6.xx.90    Brewster - initial implementation of stdio interface
  16.    7.xx.90    Patrick Bray - support for headers and forking processes
  17.    90.07.31    Ephraim - support for logging 
  18.  
  19.    91.03.03     Jonathan - set searchLog to log_out.
  20.    91.05.23    Jonathan - added fork process for indexer.
  21.                            Fixed version display so it exits.
  22.    91.05.25     Jonathan - added setuid.
  23.    
  24.    Tue Jul  9 12:11:02 1991 -- Michael Haberler mah@wu-wien.ac.at
  25.  
  26.                 Added semi-intelligent INFO database indexing (only done if
  27.         any of the .src files is newer than INFO.dct)
  28.         
  29.         Locking against multiple concurrent INFO rebuilds if 
  30.         running under inetd
  31.  
  32.         Use scandir() for directory operations
  33.  
  34.         Works under inetd as well as standalone. Here are my inetd.conf
  35.            entries (not the missing userid in the Ultrix inetd.conf!):
  36.  
  37.    hpux 7.0/800, Interactive/386 2.2.1:
  38.     z3950 stream tcp nowait root /usr/local/etc/waisserver waisserver -s \
  39.         -d /usr/logins/mah/wais-sources
  40.  
  41.    Ultrix 4.1:
  42.     z3950 stream tcp nowait /usr/local/etc/waisserver waisserver -s \
  43.         -d /usr/logins/mah/wais-sources
  44.  
  45.    Also, add the next line to /etc/services, and tickle your YP server:
  46.     z3950           210/tcp         # wide area information server (wais)
  47.  
  48.  * $Log: server-single.c,v $
  49.  * Revision 1.12  1994/12/13  19:50:18  pfeifer
  50.  * chip@chinacat.unicom.com (Chip Rosenthal) patches.
  51.  * Excluding the merge of libinv and libwais
  52.  *
  53.  * Revision 1.10  1994/10/11  14:39:04  pfeifer
  54.  * convex
  55.  *
  56.  * Revision 1.9  1994/10/06  13:28:31  pfeifer
  57.  * Patch from Mariusz Niewczas
  58.  *
  59.  * Revision 1.8  1994/09/09  09:00:28  pfeifer
  60.  * Fixed the MAX_OCCURANCES - STOP_WORD_FLAG bug
  61.  *
  62.  * Revision 1.7  1994/09/08  16:42:23  pfeifer
  63.  * make BSD happy
  64.  *
  65.  * Revision 1.6  1994/09/06  16:54:42  pfeifer
  66.  * Added #include <netinet/in.h>
  67.  *
  68.  * Revision 1.5  1994/08/08  07:32:50  pfeifer
  69.  * Moved wais_log_file_name and waislogfile to cutil.[ch]
  70.  *
  71.  * Revision 1.3  1994/05/20  12:57:05  pfeifer
  72.  * beta
  73.  *
  74.  * Revision 1.2  1994/03/08  21:06:41  pfeifer
  75.  * Patchlevel 04
  76.  *
  77.  * Revision 1.1  1993/02/16  15:05:35  freewais
  78.  * Initial revision
  79.  *
  80.  * Revision 1.8  92/05/10  14:49:06  jonathan
  81.  * Updated for release
  82.  * 
  83.  * Revision 1.7  92/03/05  07:08:23  shen
  84.  * add two more dummy arguments to call to init_search_engine
  85.  * 
  86.  * Revision 1.6  92/02/16  12:32:42  jonathan
  87.  * Removed all code refering to use_stdio, since it's not a valid choice in
  88.  * this server.
  89.  * 
  90.  * Revision 1.5  92/02/12  13:42:04  jonathan
  91.  * Changed server date.
  92.  * 
  93.  * Revision 1.4  92/02/12  13:41:18  jonathan
  94.  * Added "$Log" so RCS will put the log message in the header
  95.  * 
  96. */
  97.  
  98. #define SERVER_DATE "Sun May 10 1992"
  99.  
  100. #ifndef lint
  101. static char *RCSid = "$Header: /usr/local/ls6/src+data/src/freeWAIS-sf/ir/RCS/server-single.c,v 1.12 1994/12/13 19:50:18 pfeifer Exp $";
  102. #endif
  103.  
  104. #define INFO_DICT    "INFO.dct"
  105. #define LOCKFILE    "/tmp/INFO.lock" /* while re-indexing INFO */
  106. #define NAPTIME     1             /* seconds */
  107. #define MAXNAPTIME  60        /* wait up to a minute for indexer to finish */
  108.  
  109. #include "server.h"
  110. #include "sockets.h"
  111. /* #include <sys/types.h> */
  112. #include <sys/stat.h>
  113. #ifdef USG
  114. #ifdef HAVE_SYS_FCNTL_H
  115. #include <sys/fcntl.h>
  116. #else
  117. #include <fcntl.h>
  118. #endif /* HAVE_SYS_FCNTL_H */
  119. #else
  120. #include <sys/file.h>
  121. #endif
  122. #ifdef SYSV            
  123. #define SIGCHLD SIGCLD
  124. #endif
  125. #include <signal.h>
  126. /* #include <string.h> */
  127. #include "irdirent.h"
  128. #include "panic.h"
  129. #include "ustubs.h"
  130. #include "transprt.h"
  131. #include "wmessage.h"
  132. #include "ir.h"
  133. #include "wprot.h"
  134. #include "cutil.h"
  135. #include "futil.h"
  136. #include "irext.h"
  137.  
  138. /* to create the INFO index */
  139. #include "irtfiles.h"
  140. #include "irfiles.h"
  141. #include "irhash.h"
  142. #include "version.h"
  143.  
  144. /* for address decoding */
  145.  
  146. #if !defined(ultrix) && !defined(__convex__)
  147. #ifdef HAVE_SYS_SOCKET
  148. #include <sys/socket.h>
  149. #endif
  150. #endif
  151. #ifdef HAVE_NETINET_IN_H 
  152. #if BSD != 199103
  153. #include <netinet/in.h>
  154. #endif
  155. #endif
  156. #ifndef ultrix
  157. #ifdef HAVE_SYS_SOCKET
  158. #include <netdb.h>
  159. #endif
  160. #endif
  161. #include <arpa/inet.h>
  162.  
  163. #include <setjmp.h>
  164.  
  165. #ifdef HAVE_SYS_SELECT_H
  166. #include <sys/select.h>
  167. #endif
  168.  
  169. static jmp_buf jbuf;
  170.  
  171. static long bufferSize = BUFSZ; /* how much we are using
  172.                                    (we get one of these per process) */
  173.  
  174. static FILE *current_client;
  175. static struct itimerval new, old;
  176.  
  177. /*---------------------------------------------------------------------------*/
  178. #define TIMEOUT_LENGTH 5 /* 5 second timeout. 
  179.                 Since this is only in the handle - client code,
  180.                 I don't want it to wait too long.  
  181.                 The bytes should come quickly
  182.               */
  183. #define IDLE_TIME "5 seconds"
  184.  
  185. long
  186.  handle_client(in,out, index_directory)
  187. FILE* in;
  188. FILE* out;
  189. char *index_directory;
  190.   char buf[BUFSZ];        /* contains the message and header */
  191.   char *bufPtr ;        /* points at the begining of the z3950 */
  192.   long size;            /* bytes in the z3950 message */
  193.   WAISMessage header;        /* for storing the header */
  194.   long i;
  195.   long bytesLeft;
  196.   long nextChar;
  197.   int  jmpres;
  198.  
  199.   new.it_interval.tv_sec = 0;
  200.   new.it_interval.tv_usec = 0;
  201.   new.it_value.tv_sec = TIMEOUT_LENGTH;
  202.   new.it_value.tv_usec = 0;
  203.  
  204.   if ((jmpres = setjmp(jbuf)) != 0) {
  205.     if (jmpres == 2) return EOF; /* because we're here by timeout */
  206.   } else {
  207.     /* try to read the header */
  208.     for (i = 0; i < HEADER_LENGTH; i++)
  209.       { 
  210.     setitimer(ITIMER_REAL, &new, NULL);
  211.     nextChar = fgetc(in);
  212.     if (nextChar == EOF)    /* my connection exited, so will I */
  213.       { 
  214.         setitimer(ITIMER_REAL, &old, NULL);
  215.         return EOF;
  216.       }
  217.     else
  218.       buf[i] = (char)nextChar;
  219.       }
  220.     setitimer(ITIMER_REAL, &old, NULL);
  221.     /* parse the header */
  222.     readWAISPacketHeader(buf,&header);
  223.  
  224.     /* make sure we have the right version.  
  225.        If we dont, we dont know what to do. */
  226.     if (header.hdr_vers > HEADER_VERSION)
  227.       panic("Incompatable header versions (Current version: %d, supplied version: %d.", 
  228.         HEADER_VERSION, header.hdr_vers) ;
  229.  
  230.     /* determine the size of the z3950 message */
  231.     {
  232.       char length_array[11];
  233.       strncpy(length_array, header.msg_len, 10);
  234.       length_array[10] = '\0';
  235.       size = atol(length_array);
  236.     }
  237.  
  238.     /* set bufPtr to start the z3950 message */
  239.     bufPtr = buf + HEADER_LENGTH ;
  240.  
  241.     /* read the z3950 message */
  242.     for (i = 0; i < size ; i++) {
  243.       setitimer(ITIMER_REAL, &new, NULL);
  244.       if ((buf[i + HEADER_LENGTH] = (char)fgetc(in)) == EOF)
  245.     return -1;
  246.     }
  247.  
  248.     setitimer(ITIMER_REAL, &old, NULL);
  249.     rewind(in);
  250.  
  251.     /* decode the z3950 if necessary */
  252.     transportDecode((long)header.encoding,bufPtr,&size);
  253.      
  254.     /* XXX handle compression options */
  255.  
  256.     /* process it the z3950 */
  257.     bytesLeft = bufferSize;
  258.  
  259.     size = interpret_buffer(bufPtr,size,bufPtr,bytesLeft,
  260.                 &bufferSize,(long)header.hdr_vers,
  261.                 index_directory); 
  262.  
  263.     /* re-encode the message if necessary */
  264.     transportCode((long)header.encoding,bufPtr,&size); 
  265.  
  266.     /* XXX handle compression options */
  267.  
  268.     /* write the new header */
  269.     writeWAISPacketHeader(buf,size,
  270.               (long)header.msg_type,header.server,
  271.               (long)header.compression,(long)header.encoding,
  272.               (long)header.hdr_vers);
  273.  
  274.     /* write the whole response to the output file */
  275.     for (i = 0; i < size + HEADER_LENGTH; i++)
  276.       fputc(buf[i],out) ;
  277.  
  278.     fflush(out);        /* flush any file buffers */
  279.     rewind(out);
  280.  
  281.     return 0;
  282.   }
  283. }
  284.  
  285. /*---------------------------------------------------------------------------*/
  286.  
  287. #ifndef ISC
  288. static void breakKey _AP((long s1,long s2,struct sigcontext* s3,char* s4));
  289. #endif
  290.  
  291. static void
  292. breakKey (s1,s2,s3,s4)
  293. long s1;
  294. long s2;
  295. struct sigcontext *s3;
  296. char *s4;
  297. {
  298.   waislog(WLOG_HIGH, WLOG_ERROR, "got a ^c");
  299.   exit (-1);
  300. }
  301.  
  302. /*---------------------------------------------------------------------------*/
  303.  
  304. void
  305. childhandler(sig, code, scp, addr)
  306. long sig, code;
  307. struct sigcontext *scp;
  308. char *addr;
  309. {
  310.   wait(NULL);            /* give the kid a decent burial */
  311.   signal (SIGCHLD, childhandler);  /* Dave Judd - IRIX requires resetting signal */
  312. }
  313.  
  314. /*---------------------------------------------------------------------------*/
  315.  
  316. void
  317. server_alarmhandler(sig, code, scp, addr)
  318. long sig, code;
  319. struct sigcontext *scp;
  320. char *addr;
  321. {
  322.   setitimer(ITIMER_REAL, &old, NULL);
  323.   if(current_client != NULL) {
  324.     waislog(WLOG_HIGH, WLOG_CLOSE,
  325.         "Client idle longer %s during Read - Closing client connection.", IDLE_TIME);
  326.     longjmp(jbuf, 2);
  327.   }
  328.   else  {
  329.     waislog(WLOG_HIGH, WLOG_ERROR,
  330.         "Bogus timer signal.  What's the deal?");
  331.   }
  332. }
  333.  
  334. /*---------------------------------------------------------------------------*/
  335.  
  336. void
  337. seghandler(sig, code, scp, addr)
  338. long sig, code;
  339. struct sigcontext *scp;
  340. char *addr;
  341. {
  342.   waislog(WLOG_HIGH, WLOG_CLOSE,
  343.       "Segmentation violation.  Bummer. Closing server and exiting.");
  344.   exit(0);
  345. }
  346.  
  347. /*---------------------------------------------------------------------------*/
  348.  
  349. void
  350. bushandler(sig, code, scp, addr)
  351. long sig, code;
  352. struct sigcontext *scp;
  353. char *addr;
  354. {
  355.   waislog(WLOG_HIGH, WLOG_CLOSE,
  356.       "Bus error.  Bummer. Closing server and exiting.");
  357.   exit(0);
  358. }
  359.  
  360. /*---------------------------------------------------------------------------*/
  361.  
  362. #include <pwd.h>
  363.  
  364. int finduid(name)
  365. char *name;
  366. {
  367.   struct passwd *pwent;
  368.  
  369.   if ((pwent = getpwnam(name)) == NULL) {
  370.     return -1;
  371.   }
  372.  
  373.   return(pwent->pw_uid);
  374. }
  375.  
  376. static  char *index_dir = NULL;
  377. static  time_t info_change_time;
  378. static  int indexing_needed = 0;
  379. static  char *info_dict = INFO_DICT;
  380.  
  381. extern int alphasort();
  382.  
  383. /* selecttion function for scandir()
  384.  * trigger on ".src" extension, regular file, and != "INFO.src"
  385.  * Indexing is needed if any of the .src files is younger than 
  386.  * INFO.dct
  387.  */
  388. static int
  389. srcfiles(e)
  390.     struct dirent *e;
  391. {
  392.     struct stat sb;
  393.     char *lastdot = strrchr(e->d_name,'.');
  394.     int candidate;
  395.  
  396.     candidate =    lastdot && 
  397.           (stat(merge_pathnames(e->d_name,index_dir), &sb) >= 0) && 
  398.           ((sb.st_mode & S_IFMT) == S_IFREG) &&
  399.           !strcmp(lastdot,source_ext) && 
  400.           strcmp(e->d_name,info_dict); /* whew */
  401.  
  402.         if (candidate) {
  403.         indexing_needed |= (sb.st_mtime > info_change_time);
  404.         return 1;
  405.     }
  406.     return 0;
  407. }
  408.  
  409.  
  410. /*---------------------------------------------------------------------------*/
  411.  
  412. #include <sys/types.h>
  413. #include <sys/time.h>
  414.  
  415. typedef struct _client_connection {
  416.   FILE *file;
  417.   long buffersize;
  418.   long pid;
  419.   long line;
  420. } client_connection, *Client_connection;
  421.  
  422. void
  423. main(argc,argv)
  424. int argc;
  425. char* argv[];
  426.   fd_set fds;
  427.   FILE *file;
  428.   client_connection clients[200];
  429.   int numclients, i;
  430.   long socket;
  431.   char *next_argument = next_arg(&argc, &argv), *command_name;
  432.   long tcp_port = 210;        /* tcp_port to use */
  433.   /* char *wais_log_file_name = NULL; */    /* name of file for error output */
  434.   int child_proc;        /* for the child process id */
  435.   char *uid_name = "root";    /* user id so setuid if root */
  436.   int uid = 0;            /* if not specified, leave as root. */
  437.   long cm_mem_percent = 0;      /* default */
  438.   int child,lockfd;
  439.   struct stat statbuf;
  440.   struct dirent **list;
  441.   int n_files,fd;    
  442.   int naptime = 0;
  443.   extern int errno;
  444.   extern char *sys_errlist[];
  445.   static long current_id = 1, current_log_line = 0;
  446.   dataopsrec    dataops;  
  447.  
  448.   command_name = next_argument;
  449.  
  450. /* dgg -- must duplicate mods to irbuild.c, here is mini-build of INFO.src */
  451.   dataops.separator_function= NULL;
  452.   dataops.header_function= NULL;
  453.   dataops.date_function= NULL;
  454.   dataops.finish_header_function= NULL;
  455.   dataops.type= "WSRC";
  456.   dataops.wordDelimiter= wordbreak_notalnum;
  457.   dataops.addseparatorwords= false;
  458.   dataops.extraheaderweight= true;
  459.   dataops.repeat_weight= 1;
  460.   dataops.minwordlen= 2;
  461.   stop_list_file("\0");
  462.   gDelimiters[0]= '\0';  
  463.   wordDelimiter= wordbreak_notalnum;   
  464. /* dgg -- end new inits */
  465.  
  466.   getitimer(ITIMER_REAL, &old);
  467.   for(i = 0; i < 200; i++)
  468.     clients[i].file = NULL;
  469.  
  470.   if (argc == 0){
  471.     printf("Usage: %s [-p [port_number]] [-d directory] [-u user] [-v] [-cmmem percent]\n",
  472.        command_name);
  473.     printf(" -p [port] listen to the port.  If the port is supplied, then\n");
  474.     printf("    that tcp_port number is used.  If it is not supplied \n");
  475.     printf("    then the Z39.50 port (210) is used.\n");
  476.     printf(" -d directory: means to use the directory as the source of databases.\n");
  477.     printf("    Defaults to the current directory.\n");
  478.     printf(" -e [file]: set log output to file, or /dev/null if not specified.\n");
  479.     printf(" -u user: if started as root, setuid to user after startup.\n");
  480.     printf(" -cmmem number: percentage of CM memory to use (CM code only).\n");
  481.     printf(" -v prints the version.\n");
  482.     exit(1);
  483.   }
  484.   if(NULL == (next_argument = next_arg(&argc, &argv))){
  485.     printf("No arguments specified\n");
  486.     exit(0);
  487.   }
  488.   while((next_argument != NULL) &&
  489.     ('-' == next_argument[0])){
  490.     /* then we have an argument to process */
  491.     if (0 == strcmp("-p", next_argument)){
  492.       char *peek_argument = peek_arg(&argc, &argv);
  493.       if ((NULL != peek_argument) && /* if we are not out of args */
  494.       ('-' != peek_argument[0])){ { /* and the next isn't an option... */
  495.         /* get the port number */
  496.         tcp_port = atoi(next_arg(&argc, &argv));
  497.       }            /* end if (explicit tcp_port) */
  498.                     }
  499.     }                /* end if (-p) */
  500.  
  501.     else if (0 == strcmp("-e", next_argument)) {
  502.       char *peek_argument = peek_arg(&argc, &argv);
  503.       wais_log_file_name = "/dev/null"; /* default to /dev/null */
  504.       if ((peek_argument != NULL) &&
  505.       ('-' != peek_argument[0])) {
  506.     wais_log_file_name = next_arg(&argc, &argv);
  507.       }                /* end if (explicit log file) */
  508.     }                /* end if (-e) */
  509.     else if (0 == strcmp("-d", next_argument)) {
  510.       index_dir = next_arg(&argc, &argv);
  511.     }
  512.     else if (0 == strcmp("-v", next_argument)) {
  513.       printf("%s: %s, %s\n", command_name, VERSION, SERVER_DATE);
  514.     }
  515.     else if (0 == strcmp("-u", next_argument)) {
  516.       uid_name = next_arg(&argc, &argv);
  517.       if((uid = finduid(uid_name)) < 0)
  518.     panic("Couldn't find user %s.", uid_name);
  519.     }
  520.     else if(0 == strcmp("-cmmem", next_argument)){
  521.       if(NULL == (next_argument = next_arg(&argc, &argv)))
  522.     panic("Expected a number (1-100) for percentage of memory to use");
  523.       cm_mem_percent = atol(next_argument);
  524.       if(cm_mem_percent < 1)
  525.     panic("The -cmmem argument should not be less than 1 and less than 100");
  526.       if(cm_mem_percent > 100)
  527.     panic("Warning: The -cmmem parameter was %ld%%. It should be between 1-100.", cm_mem_percent);
  528.     }
  529.     else{
  530.       panic("Don't recognize the %s option", next_argument);
  531.     }
  532.     next_argument = next_arg(&argc, &argv);
  533.   }                /* end while (more arguments) */
  534.  
  535.   if (wais_log_file_name == NULL) {
  536.     wais_log_file_name = "/dev/null";
  537.     waislogfile = stderr;
  538.   }
  539.   else waislogfile = NULL;
  540.   
  541.   if(0 != init_search_engine(index_dir, false, true, cm_mem_percent,0,0))
  542.     panic("unable to initialize search engine");
  543.  
  544. #ifdef AUTO_INDEX
  545.  
  546.   index_dir = index_dir ? index_dir : ".";  
  547.   info_dict = s_strdup(merge_pathnames(info_dict,index_dir));
  548.   
  549.   /* remember timestamp on INFO.dct if rebuilding needed 
  550.    * If it doesnt exist, it's assumed to be *very* old, to force
  551.    * re-indexing
  552.    */
  553.   info_change_time = (stat(info_dict,&statbuf) == -1) ? 0 : statbuf.st_mtime;
  554.   
  555.   /* compare with candidates */
  556.  
  557.   if ((n_files = scandir(index_dir, &list, srcfiles, alphasort)) < 0) {
  558.     waislog(WLOG_HIGH, WLOG_ERROR, 
  559.         "Error: reading directory %s, %s", 
  560.         index_dir, sys_errlist[errno]);
  561.     exit(1);
  562.   }
  563.   
  564.   /* ok. we know if we need indexing, 
  565.    * and have all the filenames. 
  566.    */
  567.   
  568.   if ((info_change_time == 0) || indexing_needed) {
  569.  
  570.     /* Time to re-index,
  571.      * aquire the lock 
  572.      */
  573.     waislog(WLOG_MEDIUM, WLOG_INDEX,
  574.         "re-indexing needed, info_change_time=%d",info_change_time); 
  575.  
  576.     if (( fd = open(LOCKFILE, O_WRONLY|O_CREAT|O_EXCL,0666)) == -1) {
  577.       
  578.       /* already locked by somebody else
  579.        * spin  till she finishes
  580.        */
  581.       while (!(stat(LOCKFILE,&statbuf) == -1)) {
  582.     sleep(NAPTIME);
  583.     naptime += NAPTIME;
  584.     waislog(WLOG_MEDIUM, WLOG_INFO,
  585.         "INFO locked, waiting since %d seconds", naptime);
  586.     if (naptime  > MAXNAPTIME)  {
  587.       waislog(WLOG_HIGH, WLOG_ERROR,
  588.           "Warning - lockfile %s wont go away after %d seconds, exiting", 
  589.           LOCKFILE, naptime);
  590.       exit(1);        /* XXX be more perseverant */
  591.     }
  592.       }
  593.       /* lockfile went away, assume INFO.* build finished
  594.        * so just use it
  595.        */
  596.     } else {            /* we aquired the lock, so rebuild database  */
  597.       
  598.       if (!(child = fork())) {
  599.     database *db;
  600.     struct dirent **s = list;
  601.     char filename[MAX_FILENAME_LEN];
  602.           
  603.     waislog(WLOG_MEDIUM, WLOG_INDEX,
  604.         "Creating INFO database, pid=%d",getpid());
  605.     db = openDatabase(merge_pathnames("INFO",    index_dir),
  606.               true, /* maybe this should append XXX */
  607.               false);
  608.     db->the_word_memory_hashtable =
  609.       init_word_memory_hashtable(1L<<16, 100000, db->the_word_memory_hashtable);
  610.           
  611.     while (*s) {        /* index it */
  612.       strncpy(filename, index_dir, MAX_FILENAME_LEN);
  613.       if(index_dir[strlen(index_dir) -1] != '/')
  614.         strncat(filename, "/", MAX_FILENAME_LEN);
  615.       strncat(filename, (*s)->d_name, MAX_FILENAME_LEN);
  616.       waislog(WLOG_MEDIUM, WLOG_INDEX,
  617.           "Indexing %s", filename);
  618.       index_text_file(filename, &dataops, db, true, false);
  619.       s++;
  620.     }
  621.     freedir(list);        /* array of filenames */
  622.           
  623.     if(!probe_file(source_filename(filename, db)))
  624.       write_src_structure(source_filename(filename, db),
  625.                   "INFO", "WSRC", NULL, 0, true, tcp_port);
  626.     finished_add_word(db);
  627.     closeDatabase(db);
  628.     if (unlink(LOCKFILE))
  629.       panic("Indexer: cant unlink lockfile!\n");
  630.     waislog(WLOG_MEDIUM, WLOG_INDEX,
  631.         "Indexer pid=%d done", getpid());
  632.           
  633.     exit(0);        /* indexing child */
  634.  
  635.       }  else if (child == -1) {
  636.     waislog(WLOG_HIGH, WLOG_ERROR,
  637.         "Unable to fork for indexer.");
  638.     exit(1);
  639.       }
  640.       /* wait for child process */
  641.       else while (wait(0) != child) ; /* do nothing */
  642.     }
  643.   }
  644.  
  645. #endif                /* AUTO_INDEX */
  646.  
  647.   waislog(WLOG_MEDIUM, WLOG_INFO, "Running server %s", VERSION);
  648.  
  649.   signal(SIGINT, breakKey);
  650.  
  651.   signal(SIGCHLD, childhandler); /* XXX dont really need this any more */
  652.   signal(SIGALRM, server_alarmhandler);
  653.  
  654.   signal(SIGSEGV, seghandler);
  655.  
  656.   signal(SIGBUS, bushandler);
  657.  
  658.   open_server(tcp_port,&socket,BUFSZ);
  659.  
  660. #ifdef SECURE_SERVER
  661.     /* if root, setuid to user specified id. */
  662.     if (uid > 0 && getuid() == 0)  {
  663.       waislog(WLOG_MEDIUM, WLOG_INFO,
  664.           "Setting uid to %s.", uid_name);
  665.       if ( 0 > setuid(uid)) {
  666.     waislog(WLOG_HIGH, WLOG_ERROR,
  667.         "Unable to setuid to %s!  Exiting.", uid_name);
  668.     exit(-1);
  669.       }
  670.     }
  671. #endif
  672.     while (TRUE) {        /* be a server for several connections */
  673.       int active, width = ulimit();
  674.  
  675.       FD_ZERO(&fds);
  676.       FD_SET(socket, &fds);
  677.       wais_pid = 0;
  678.       for (i = 0; i < 200; i++) {
  679.     if (clients[i].file != NULL)
  680.       FD_SET(fileno(clients[i].file), &fds);
  681.       }
  682.       if((active = select(width, &fds, NULL, NULL, NULL)) < 1) {
  683.     perror ("Select: ");
  684.     waislog(WLOG_HIGH, WLOG_ERROR, 
  685.         "select returned an error!");
  686.       }
  687.       else {
  688.     /* this is a connection on the socket. */
  689.     if (FD_ISSET(socket, &fds)) {
  690.       for(i = 0; i < 200; i++) {
  691.         if (clients[i].file == NULL) {
  692.           current_log_line++;
  693.           accept_client_connection(socket, &clients[i].file);
  694.           current_client = clients[i].file;
  695.           clients[i].buffersize = BUFSZ;
  696.           wais_pid = clients[i].pid = current_id++;
  697.           log_line = clients[i].line = 0;
  698.           if (handle_client(current_client, current_client, index_dir) == -1)  {
  699.         close_client_connection(current_client);
  700.         current_client = clients[i].file = NULL;
  701.         waislog(WLOG_MEDIUM, WLOG_CLOSE,
  702.             "Done handling client");
  703.         log_line = current_log_line;
  704.           }
  705.           else {
  706.         setitimer(ITIMER_REAL, &old, NULL);
  707.         clients[i].buffersize = bufferSize;
  708.         clients[i].line = log_line;
  709.         log_line = current_log_line;
  710.         wais_pid = 0;
  711.           }
  712.  
  713.           break;
  714.         }
  715.       }
  716.     }
  717.     /* this is for an established connection */
  718.  
  719.     for(i = 0; i < 200; i++) {
  720.       if(clients[i].file != NULL && FD_ISSET(fileno(clients[i].file), &fds)) {
  721.         current_client = clients[i].file;
  722.         bufferSize = clients[i].buffersize;
  723.         wais_pid = clients[i].pid;
  724.         log_line = clients[i].line;
  725.         if (handle_client(current_client, current_client, index_dir) == -1) {
  726.           close_client_connection(current_client);
  727.           current_client = clients[i].file = NULL;
  728.           waislog(WLOG_MEDIUM, WLOG_CLOSE,
  729.               "Done handling client");
  730.           wais_pid = 0;
  731.           log_line = current_log_line;
  732.         }
  733.         else setitimer(ITIMER_REAL, &old, NULL);
  734.         clients[i].line = log_line;
  735.       }
  736.     }
  737.       }
  738.     }
  739. }    
  740.  
  741. /*---------------------------------------------------------------------------*/
  742.  
  743.